package edu.hawaii.myisern.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import edu.hawaii.myisern.collaborations.jaxb.Collaboration;
import edu.hawaii.myisern.organizations.jaxb.Organization;
import edu.hawaii.myisern.researchers.jaxb.Researcher;

/**
 * A checker to verify the links among researchers, organizations, and collaborations.
 * 
 * @author Edward Kim
 * @author JianFei Liao
 * @author KaYee Leung
 */
public class MyIsernChecker {
  
  /** A list with all researchers. */
  private List<Researcher> researchersList;
  /** A list with all organizations. */
  private List<Organization> organizationsList;
  /** A list with all collaborations. */
  private List<Collaboration> collaborationsList;
  /** A map that associates every researcher with an unique ID. */
  private Map<String, Researcher> researchersMap;
  /** A map that associates every organization with an unique ID. */
  private Map<String, Organization> organizationsMap;
  
  /**
   * Create a new instance of the checker.
   * 
   * @param model The MyISERN instance that will be checked.
   */
  public MyIsernChecker(MyIsernModel model) {
    // get all researchers, organizations, and collaborations as lists
    this.researchersList = model.getResearchersList();
    this.organizationsList = model.getOrganizationsList();
    this.collaborationsList = model.getCollaborationsList();
    // get all researchers, organizations, and collaborations as maps
    this.researchersMap = model.getResearchersMap();
    this.organizationsMap = model.getOrganizationsMap();
  }  
  
  /**
   * Checks to see if the organization associated with a researcher is valid. 
   * This check will be performed for all researchers.
   * 
   * @return A list of invalid organizations.
   */
  public synchronized List<String> invalidOrganizationLinksForResearchers() {
    List<String> list = new ArrayList<String>();
    // check the organization link for every researcher
    for (Researcher curResearcher : this.researchersList) {
      String tempId = curResearcher.getOrganization().replace(' ', '_');
      // save the link if the organization does not exist, exclude link that is an empty string
      if ((!this.organizationsMap.containsKey(tempId) || this.organizationsMap.get(tempId) == null)
          && !curResearcher.getOrganization().equals("")) {
        String string = curResearcher.getOrganization() + " in researcher: "
            + curResearcher.getName();
        list.add(string);
        }
    }
    return list;
  }
  
  /**
   * Checks to see if the researchers associated with an organization is valid.
   * This check will be performed for all organizations.
   * 
   * @return A link of invalid affiliated researchers.
   */
  public synchronized List<String> invalidResearchersLinksForOrganizations() {
    List<String> list = new ArrayList<String>();
    // check the affiliated researchers link for every organization
    for (Organization curOrganization : this.organizationsList) {
      List<String> affiliatedResearchersList = curOrganization.getAffiliatedResearchers()
          .getAffiliatedResearcher();
      // save the link if the presented affiliated researcher does not exist
      for (String curResearcherName : affiliatedResearchersList) {
        String tempId = curResearcherName.replace(' ', '_');
        if (!this.researchersMap.containsKey(tempId) || this.researchersMap.get(tempId) == null) {
          String string = curResearcherName + " in organization: " + curOrganization.getName();
          list.add(string);
        }
      }
    }
    return list;
  }
  
  /**
   * Checks to see if the organizations associated with a collaboration is valid. 
   * This check will be performed for all collaborations.
   * 
   * @return A list of all invalid collaborating organizations.
   */
  public synchronized List<String> invalidCollabOrganizationsLinksForCollaborations() {
    List<String> list = new ArrayList<String>();
    // check the collaborating organizations link for every collaboration
    for (Collaboration curCollaboration : this.collaborationsList) {
      List<String> collaboratingOrganizationsList = curCollaboration
          .getCollaboratingOrganizations().getCollaboratingOrganization();
      // save the link if the presented collaborating organization does not exist
      for (String curOrganizationName : collaboratingOrganizationsList) {
        String tempId = curOrganizationName.replace(' ', '_');
        if (!this.organizationsMap.containsKey(tempId) 
            || this.organizationsMap.get(tempId) == null) {
          String string = curOrganizationName + " in collaboration: " + curCollaboration.getName();
          list.add(string);
        }
      }
    }
    return list;
  }
}